﻿#include "graphshow.h"

GraphShow::GraphShow(QWidget *parent)
	: QWidget(parent)	
{
	ui.setupUi(this);
	connect(ui.pushButton_pixel_analyse, SIGNAL(clicked()),this,SLOT(pixelAnalyse()));
	//connect(ui.pushButton_spectrum_distance, SIGNAL(clicked()), this, SLOT(updateText()));
	//connect(ui.widget_graph, SIGNAL(getText(QString)),this, SLOT(receiveText(QString)));
	//connect(ui.widget_graph, SIGNAL(getText(QString)), this, SLOT(updateString(QString)));
	connect(ui.pushButton_fitting, SIGNAL(clicked()), this, SLOT(noLinearfittingCalcu()));
	connect(ui.pushButton_linear_fitting, SIGNAL(clicked()), this, SLOT(linearfitting()));
	connect(ui.pushButton_intencity_correct, SIGNAL(clicked()), this, SLOT(crrectFactorInput()));
	connect(ui.pushButton_zoom, SIGNAL(clicked()), this, SLOT(zoomerSet()));

	//connect(ui.pushButton_fitting, SIGNAL(clicked()), this, SLOT(fittingCalcu()));
	connect(ui.qwtPlot_curve, SIGNAL(selected(const double)), this, SLOT(getXLPos(double)));
	connect(ui.qwtPlot_curve, SIGNAL(selected(const double)), this, SLOT(getXRPos(double)));
	connect(ui.pushButton_getpos, SIGNAL(clicked()), this, SLOT(getPosValue()));

//	ui.widget_graph->setCurveFlag(false);

	//setWindowFlags(Qt::WindowStaysOnTopHint);//让窗口显示在主窗口前方
	//setWindowFlags(windowFlags()& ~Qt::WindowMaximizeButtonHint);//禁用最大化按钮
	//setWindowModality(Qt::WindowModal);//窗口模态显示

	//ui.widget_graph->setFixedSize(1358, 350);
	//ui.label_image_grashow->setFixedSize(1350, 200);
	setWindowState(Qt::WindowMaximized);
	curve_plot_state = false;
	standard_lamda.append(491.60);
	standard_lamda.append(546.07);
	standard_lamda.append(578.02);
	canvasInitial();
	namCurInitial();
}

GraphShow::~GraphShow()
{
	ui.qwtPlot_curve->detachItems();
}

//接收鼠标事件返回的矩形框
void GraphShow::setRect( const QRect rectangle)
{
	gra_rectangle = rectangle;
}

//将原图中这个矩形的图像数据copy到scr_rect_image中
void GraphShow::setRectImage(QPixmap org_image)
{
	scr_rect_image = org_image.copy(gra_rectangle);
}

void GraphShow::showRectImage()
{
	ui.label_image_grashow->setPixmap(scr_rect_image);
	ui.label_image_grashow->resize(scr_rect_image.width(), scr_rect_image.height());
}

void GraphShow::setRectImageData(QImage org_image_data)
{
		rect_image_data = org_image_data.copy(gra_rectangle);
}

void GraphShow::gaussianBlur(QImage ima)
{
	cv::Mat matInput;
	//彩色图像去燥
	//matInput = cv::Mat(ima.height(), ima.width(), CV_8UC3, (void*)ima.constBits(), ima.bytesPerLine());
	//cv::cvtColor(matInput, matInput, CV_BGR2RGB);
	//GaussianBlur(matInput, matOut, Size(5, 5), 0, 0);
	

	//灰度图像去燥
	matInput = cv::Mat(ima.height(), ima.width(), CV_8UC1, (void*)ima.constBits(), ima.bytesPerLine());
	//高斯滤波
	GaussianBlur(matInput, matOut, Size(5, 5), 0, 0);
	//方框滤波
	//boxFilter(matInput, matOut, -1, Size(7, 7));
	//均值滤波前后
	//blur(matInput,matOut,Size(7,7));
	//中值滤波
	//medianBlur(matInput,matOut,17);
	//双边滤波
	//bilateralFilter(matInput,matOut,95,95*2,95/2);
}
QImage GraphShow::matIma2Qimage(Mat ima)
{
	//彩色图像去燥
	//const uchar *pSrc = (const uchar*)ima.data;
	//QImage image(pSrc, ima.cols, ima.rows, ima.step, QImage::Format_RGB888);
	//return image.rgbSwapped();

//	灰度图像去噪
	QImage image(ima.cols, ima.rows, QImage::Format_Indexed8);
	 
	image.setColorCount(256);
	for (int i = 0; i < 256; i++)
	{
		image.setColor(i, qRgb(i, i, i));
	}
	// Copy input Mat  
	uchar *pSrc = ima.data;
	for (int row = 0; row < ima.rows; row++)
	{
		uchar *pDest = image.scanLine(row);
		memcpy(pDest, pSrc, ima.cols);
		pSrc += ima.step;
	}
	return image;
}

void GraphShow::setCurveData()
{
	//ui.widget_graph->setImageData(rect_image_data);
}

//画像素值分析线
void GraphShow::pixelAnalyse()
{
	curve_plot_state = true;
	//ui.widget_graph->setCurveFlag(true);
	update();
	///qwt
	curvePlot();
	peakValueSearch(plot_data);
	pValueShow(pValue);
}
void GraphShow::updateText()
{
	ui.label_distance->setText(text_show);
}
//接收间距
void GraphShow::receiveText(QString text)
{
	text_show = text;
}
//谱线间距更新显示
void GraphShow::updateString(QString string)
{
	ui.label_distance->setText(text_show);
}


void GraphShow::tableWidget()
{
	//table_show.show();
	update();
	namCurvePlot();
}

void GraphShow::getPlotData(QImage image)
{
	plot_data.clear();
	int data_len = gra_rectangle.width() - 1;
	//int width =m_image_data.width();
	//int height = m_image_data.height();

	int pixel_num = 80;//纵向遍历的像素点个数
	for (int i = 1; i < data_len + 1; i++)
	{
		int sum = 0;
		for (int j = 0; j < pixel_num + 1; j++)
		{
			QRgb pixel_rgb = image.pixel(i, gra_rectangle.height() / 2 - 39 + j);
			int pixel_gray = qGray(pixel_rgb);
			sum = sum + pixel_gray;
		}
		plot_data.append(sum / pixel_num);
	}
}

//像素-灰度值曲线
void GraphShow::curvePlot()
{
	if (curve_plot_state == true)
	{
		//ui.qwtPlot_curve->detachItems();
		
		//图像滤波去噪
		gaussianBlur(rect_image_data);
		rect_image_data = matIma2Qimage(matOut);
		getPlotData(rect_image_data);

		QwtPlotCurve *plot = new QwtPlotCurve("pixel-grayvalue");
		plot->setRenderHint(QwtPlotItem::RenderAntialiased);
		plot->setLegendAttribute(QwtPlotCurve::LegendShowLine, true);
		plot->setPen(Qt::red);
		plot->attach(ui.qwtPlot_curve);

		//构造曲线数据image To pointdata
		QPolygonF points;
		for (int i = 0; i < plot_data.size(); i++)
		{
			points << QPointF(i, plot_data.at(i));
		}
		plot->setSamples(points);
		
		ui.qwtPlot_curve->replot();
	}
}

//波长-灰度值曲线
void GraphShow::namCurvePlot()
{
	
	QwtPlotCurve *plot = new QwtPlotCurve("namda-grayvalue");
		plot->detach();
		plot->setRenderHint(QwtPlotItem::RenderAntialiased);
		plot->setLegendAttribute(QwtPlotCurve::LegendShowLine, true);
		plot->setPen(Qt::red);
		plot->attach(ui.qwtPlot_namda_curve);

		QPolygonF nam_points;
		for (int i = 0; i < plot_data.size(); i++)
		{
			nam_points << QPointF(NamdaCalculate((double)i), plot_data.at(i));
		}
		plot->setSamples(nam_points);

		ui.qwtPlot_namda_curve->replot();
}

void GraphShow::linearnamCurvePlot()
{ 

	QwtPlotCurve *plot = new QwtPlotCurve("namda-grayvalue");
	plot->detach();
	plot->setRenderHint(QwtPlotItem::RenderAntialiased);
	plot->setLegendAttribute(QwtPlotCurve::LegendShowLine, true);
	plot->setPen(Qt::red);
	plot->attach(ui.qwtPlot_namda_curve);

	QPolygonF nam_points;
	for (int i = 0; i < plot_data.size(); i++)
	{
		nam_points << QPointF(linearNamdaCalculate((double)i), plot_data.at(i));
	}
	plot->setSamples(nam_points);

	ui.qwtPlot_namda_curve->replot();
}

void GraphShow::canvasInitial()
{
	
	//坐标轴
	ui.qwtPlot_curve->setAxisTitle(QwtPlot::xBottom, "pixel");
	ui.qwtPlot_curve->setAxisScale(QwtPlot::xBottom, 0.0, 1300);
	ui.qwtPlot_curve->setAxisMaxMajor(QwtPlot::xBottom, 13);
	//ui.qwtPlot_curve->setAxisMaxMinor(QwtPlot::xBottom, 5);//间隔数5
	ui.qwtPlot_curve->setAxisAutoScale(QwtPlot::xBottom, true);

	ui.qwtPlot_curve->setAxisTitle(QwtPlot::yLeft, "gray value");
	ui.qwtPlot_curve->setAxisScale(QwtPlot::yLeft, 0, 260);
	ui.qwtPlot_curve->setAxisMaxMajor(QwtPlot::yLeft, 10);
	//ui.qwtPlot_curve->setAxisMaxMinor(QwtPlot::yLeft, 5);//间隔数5
	ui.qwtPlot_curve->setAxisAutoScale(QwtPlot::yLeft, true);

	//ui.qwtPlot_curve->enableAxis(QwtPlot::yRight, true);
	//ui.qwtPlot_curve->enableAxis(QwtPlot::xTop, true);

	//canvas
	ui.qwtPlot_curve->setLineWidth(1);
	ui.qwtPlot_curve->setFrameStyle(QFrame::Box | QFrame::Raised);
	ui.qwtPlot_curve->setCanvasBackground(QColor(29, 100, 141));



	//网格线
	QwtPlotGrid *grid = new QwtPlotGrid;
	grid->enableX(true);
	grid->enableY(true);
	grid->setMajorPen(Qt::gray, 0, Qt::SolidLine);
	grid->attach(ui.qwtPlot_curve);

}

void GraphShow::namCurInitial()
{
	//坐标轴
	ui.qwtPlot_namda_curve->setAxisTitle(QwtPlot::xBottom, "namda");
	ui.qwtPlot_namda_curve->setAxisScale(QwtPlot::xBottom, 300, 1000);
	ui.qwtPlot_namda_curve->setAxisMaxMajor(QwtPlot::xBottom, 7);
	ui.qwtPlot_namda_curve->setAxisAutoScale(QwtPlot::xBottom, true);

	ui.qwtPlot_namda_curve->setAxisTitle(QwtPlot::yLeft, "gray value");
	ui.qwtPlot_namda_curve->setAxisScale(QwtPlot::yLeft, 0, 260);
	ui.qwtPlot_namda_curve->setAxisMaxMajor(QwtPlot::yLeft, 10);
	ui.qwtPlot_namda_curve->setAxisAutoScale(QwtPlot::yLeft, true);
	//画布
	ui.qwtPlot_namda_curve->setLineWidth(1);
	ui.qwtPlot_namda_curve->setFrameStyle(QFrame::Box | QFrame::Raised);
	ui.qwtPlot_namda_curve->setCanvasBackground(QColor(29, 100, 141));
	//网格线
	QwtPlotGrid *grid = new QwtPlotGrid;
	grid->enableX(true);
	grid->enableY(true);
	grid->setMajorPen(Qt::gray, 0, Qt::SolidLine);
	grid->attach(ui.qwtPlot_namda_curve);
}


void GraphShow::mouseMoveEvent(QMouseEvent* e)
{
	//坐标显示
	QwtPlotPicker *m_picker = new QwtPlotPicker(QwtPlot::xBottom, QwtPlot::yLeft,
		QwtPlotPicker::CrossRubberBand, QwtPicker::AlwaysOn, ui.qwtPlot_curve->canvas());

	//m_picker->setStateMachine(new QwtPickerDragPointMachine());
	m_picker->setTrackerPen(QColor(Qt::green));
	m_picker->setRubberBandPen(QColor(Qt::green));	

}

void GraphShow::mousePressEvent(QMouseEvent* e)
{
	if (curve_plot_state == true)
	{
		if (pos_value_state == true)
		{
			if (e->button() == Qt::LeftButton)
			{
				double fXOffset = 80.15;
				double fYOffset = 624.09;

				double fX = ui.qwtPlot_curve->invTransform(QwtPlot::xBottom, e->pos().x()) - fXOffset;
				double fY = -(ui.qwtPlot_curve->invTransform(QwtPlot::yLeft, e->pos().y()) + fYOffset);

				peak_point = QPoint(fX, fY);

				m_table.showItem();

				if (pos_value_state == true)
				{
					if (curve_plot_state == true)
					{
 						addPos2List(fX);
						wavelengthInput();
					}
				}
				qDebug() << " ";
			}
		}
		else
		{
			QMessageBox::about(this, QStringLiteral("提示"), QStringLiteral("请先取值!"));
		}
	}
	else
	{
		QMessageBox::about(this, QStringLiteral("提示"), QStringLiteral("请先画曲线!"));
	}
}

//非线性拟合响应函数
void GraphShow::noLinearfittingCalcu()
{
	//newTableWid();
	namCurvePlot();
}

void GraphShow::linearfitting()
{
	linearnamCurvePlot();
	staParaShow();
}

void GraphShow::newTableWid()
{
	QTableWidget *tableWidget = new QTableWidget;
	tableWidget->setRowCount(5);//设置行数为5
	tableWidget->setColumnCount(2);//设置列数为2
	tableWidget->setGeometry(QRect(800, 400, 401, 241));//设置tableWidget的大小

	tableWidget->setItem(0, 0, new QTableWidgetItem("579.0"));
	tableWidget->setItem(1, 0, new QTableWidgetItem("577.0"));
	tableWidget->setItem(2, 0, new QTableWidgetItem("546.1"));
	tableWidget->setItem(3, 0, new QTableWidgetItem("435.8.0"));
	tableWidget->setItem(4, 0, new QTableWidgetItem("404.7"));

	tableWidget->setHorizontalHeaderLabels(QStringList() << tr("namda") << tr("pixel value"));

	tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);   //设置选择的模式为单选择
	//tableWidget->setWindowFlags(Qt::Dialog); 
	tableWidget->setWindowModality(Qt::WindowModal);
	tableWidget->setStyleSheet("background-color: #000000;color: #ffffff;");
	tableWidget->show();
}

//取值响应函数
void GraphShow::getPosValue()
{
	 int inform_state = QMessageBox::information(NULL, QStringLiteral("提示"), QStringLiteral("请输入三个标准数据"), 
		 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);

	 qDebug() << inform_state;

	 if (inform_state == QMessageBox::Yes)
	 {
		 //standard_lamda.clear();
		 standard_pos.clear();
		 staWlength.clear();
		 pos_value_state = true;
		 pos_lenghth = 3;
	 }
}

//取点存入poslist
void GraphShow::addPos2List(double pos_fx)
{
	if (pos_lenghth > 0)
	{
		standard_pos.append(pos_fx);

		//QMessageBox::about(this, QStringLiteral("提示"), QStringLiteral("请输入对应位置的标准光源波长!"));
		//standard_lamda.append(namda);
		pos_lenghth--;
	}
	else
	{
		pos_value_state == false;
		QMessageBox::about(this, QStringLiteral("提示"), QStringLiteral("数据已满，若想重新输入请再次点击取值按钮!"));
	}
}

//非线性未知波长计算
double GraphShow::NamdaCalculate(double unde_namda_pos)
{
	QList<double> coefficient_value;
	double undet_namda;

	coefficient_value = NoLinearFitting(standard_pos, staWlength);
	undet_namda = coefficient_value.at(0) + (coefficient_value.at(1) * unde_namda_pos) + (coefficient_value.at(2) * unde_namda_pos*unde_namda_pos);
	return undet_namda;
}

//线性波长
double GraphShow::linearNamdaCalculate(double unde_namda_pos)
{
	QList<double> coefficient_value;
	double undet_namda;

	coefficient_value = LinearFitting(standard_pos, staWlength);
	undet_namda = coefficient_value.at(0) + (coefficient_value.at(1) * unde_namda_pos) ;
	return undet_namda;
}

//克莱姆法则,计算系数
QList<double> GraphShow::NoLinearFitting(QList<double> positions, QList<double> lamdas)
{
	if (positions.size() == 3 && lamdas.size() == 3)
	{
		QList<double> result;
		double  a1 = 1, b1 = positions.at(0), c1 = positions.at(0) * positions.at(0), d1 = lamdas.at(0);
		double  a2 = 1, b2 = positions.at(1), c2 = positions.at(1) * positions.at(1), d2 = lamdas.at(1);
		double  a3 = 1, b3 = positions.at(2), c3 = positions.at(2) * positions.at(2), d3 = lamdas.at(2);

		float x, y, z, D, D1, D2, D3;
		D = a1*b2*c3 + b1*c2*a3 + c1*a2*b3 - (c1*b2*a3 + b1*a2*c3 + a1*c2*b3);
		D1 = d1*b2*c3 + b1*c2*d3 + c1*d2*b3 - (c1*b2*d3 + b1*d2*c3 + d1*c2*b3);
		D2 = a1*d2*c3 + d1*c2*a3 + c1*a2*d3 - (c1*d2*a3 + d1*a2*c3 + a1*c2*d3);
		D3 = a1*b2*d3 + b1*d2*a3 + d1*a2*b3 - (d1*b2*a3 + b1*a2*d3 + a1*d2*b3);
		if (D == 0)
		{
			x = 0;
			y = 0; 
			z = 0;
		}
		x = D1 / (float)D;
		y = D2 / (float)D;
		z = D3 / (float)D;

		result.append(x);
		result.append(y);
		result.append(z);
		return result;
	}

}

QList<double> GraphShow::LinearFitting(QList<double> positions, QList<double> lamdas)
{

	if (positions.size() == 3 && lamdas.size() == 3)
	{
		QList<double> result;
		double  a1 = 1, b1 = positions.at(0),  d1 = lamdas.at(0);
		double  a2 = 1, b2 = positions.at(1),  d2 = lamdas.at(1);

		float x, y,  D, D1, D2;
		D = (a1*b2)- (b1*a2);
		D1 = (d1*b2)-(b1*d2);
		D2 = (a1*d2)-(d1*a2);

		if (D == 0)
		{
			x = 0;y = 0;
		}
		x = D1 / (float)D;
		y = D2 / (float)D;
		result.append(x);
		result.append(y);
		return result;
	}
}

void GraphShow::zoomerSet()
{
	//QwtPlotZoomer *zoomer = new QwtPlotZoomer(ui.qwtPlot_namda_curve->canvas());                     //选择图形局部放大
	//zoomer->setRubberBandPen(QColor(Qt::blue)); //勾选扩大区域边界颜色
	//zoomer->setMousePattern(QwtEventPattern::MouseSelect2, Qt::LeftButton, Qt::ControlModifier);//ctrl+右键==回复到原始状态 
	//zoomer->setMousePattern(QwtEventPattern::MouseSelect3, Qt::LeftButton);       //右键==恢复到上一次扩大之前的状态

	QwtPlotPanner *panner = new QwtPlotPanner(ui.qwtPlot_namda_curve->canvas());                                   //默认的左键移动功能
	panner->setMouseButton(Qt::RightButton);        //设置右键平移
	QwtPlotMagnifier *magnifier = new QwtPlotMagnifier(ui.qwtPlot_namda_curve->canvas());                 //默认的滑轮及右键缩放功能  图形的整体缩放
	magnifier->setMouseButton(Qt::RightButton);     //右键为缩放
}

QVector<double> GraphShow::intencityCorrect(QVector<int> intencity_val, double corect_factor)
{
	QVector<double> correct_intencity;
	double temp;
	for (int i = 0; i < intencity_val.size(); i++)
	{
		temp = intencity_val.at(i) * corect_factor;
		correct_intencity.append(temp);
	}
	return correct_intencity;
}

void GraphShow::crrectFactorInput()
{
	bool ok;
	double high = QInputDialog::getDouble(this, QStringLiteral("修正系数"),QStringLiteral("请输入修正系数:"), 1.5, 1, 10.00, 1, &ok);
	if (ok)
	{
		intensity_correct_fac = high;
	}
}

void GraphShow::wavelengthInput()
{
	bool ok;
	double temp = QInputDialog::getDouble(this, QStringLiteral("标准波长输入对话框"), QStringLiteral("请输入标准波长："),0,0,1000,1,&ok);
	if (ok)
	{
		staWavelen = temp;
		staWlength.append(staWavelen);
	}
}
void GraphShow::peakValueSearch(QVector<int> vector)
{
	int count = vector.size();
	QVector<int> sign;
	for (int i = 1; i < count; i++)
	{
		/*相邻值做差：*小于0，赋-1*大于0，赋1*等于0，赋0*/
		int diff = vector.at(i) - vector.at(i - 1);
		if (diff > 0)
		{
			sign.push_back(1);
		}
		else if (diff < 0)
		{
			sign.push_back(-1);
		}
		else
		{
			sign.push_back(0);
		}
	}
	//再对sign相邻位做差 ,保存极大值和极小值的位置  
	QVector<int> indexMax;
	int num = sign.size();
	for (int j = 1; j < num; j++)
	{
		int diff = sign.at(j) - sign.at(j - 1);
		if (diff < 0)
		{
			indexMax.push_back(j);
		}
	}
	for (int m = 0; m < indexMax.size(); m++)
	{
		pValue.push_back(vector.at(indexMax.at(m)));
	}
}
	void GraphShow::pValueShow(QVector<int> vector)
	{
		int count = vector.size();
		QStringList valstring;
		for (int i = 0; i < count; i++)
		{
			double temp = vector.at(i);
			if (i == 0)
			{
				valstring << QStringLiteral("val: ") + QString::number(temp);
			}
			else
				valstring << QStringLiteral("      ")+QString::number(temp);
		}
		QStringListModel * listmodel = new QStringListModel(valstring);
		ui.listView_peakGValue->setModel(listmodel);
	}

	void GraphShow::staParaShow()
	{
		QStringList parString;
		for (int i = 0; i < 3; i++)
		{
			double tempW = staWlength.at(i);
			double tempP = standard_pos.at(i);
			if (i == 0)
			{
				parString << QStringLiteral("parW:") + QString::number(tempW) + QStringLiteral("      ") + QStringLiteral("parP:") + QString::number(tempP);
			}
			else
			{
				parString << QStringLiteral("         ") + QString::number(tempW) + QStringLiteral("              ") + QString::number(tempP);
			}
				
		}
		QStringListModel * listmodel = new QStringListModel(parString);
		ui.listView_staParameter->setModel(listmodel);
	}